package cn.skycity.common.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.skycity.common.mapper.SysUserMapper;
import cn.skycity.common.mapper.SysUserRoleMapper;
import cn.skycity.common.service.ISysUserService;
import cn.skycity.framework.core.exception.ServiceException;
import cn.skycity.framework.core.utils.StreamUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.skycity.common.excel.utils.ExcelUtil;
import com.skycity.framework.uaa.pojo.dto.SysUserBo;
import com.skycity.framework.uaa.pojo.entity.SysUser;
import com.skycity.framework.uaa.pojo.entity.SysUserRole;
import com.skycity.framework.uaa.pojo.vo.SysUserExportVo;
import com.skycity.framework.uaa.pojo.vo.SysUserVo;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @author daiyb2
 * @Title: SysUserServiceImpl
 * @Description:
 * @date 2021/10/30 19:19
 **/
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    @Resource
    private SysUserRoleMapper sysUserRoleMapper;

    @Override
    public Page<SysUserVo> selectPageList(IPage<SysUserVo> page, SysUserBo sysUser) {
        return baseMapper.selectUserList(page,sysUser);
    }

    @Override
    public SysUser getByUsername(String username) {
        return baseMapper.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, username));
    }

    @Override
    public SysUserVo selectUserById(Long userId) {
        return baseMapper.getUserById(userId);
    }

    @Override
    public Page<SysUserVo> selectAllocatedList(SysUserBo user, Page<SysUserBo> pageQuery) {
        return baseMapper.selectAllocatedList(pageQuery, user);
    }

    @Override
    public Page<SysUserVo> selectUnallocatedList(SysUserBo user, Page<SysUserBo> pageVo) {
        return baseMapper.selectUnallocatedList(pageVo, user);
    }

    @Override
    public boolean checkUserNameUnique(SysUserBo user) {
        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUserName, user.getUserName())
                .ne(ObjectUtil.isNotNull(user.getId()), SysUser::getId, user.getId()));
        return !exist;
    }

    @Override
    public boolean checkMobileUnique(SysUserBo user) {
        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getMobile, user.getMobile())
                .ne(ObjectUtil.isNotNull(user.getId()), SysUser::getId, user.getId()));
        return !exist;
    }

    @Override
    public boolean checkEmailUnique(SysUserBo user) {
        boolean exist = baseMapper.exists(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getEmail, user.getEmail())
                .ne(ObjectUtil.isNotNull(user.getId()), SysUser::getId, user.getId()));
        return !exist;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateUser(SysUserBo user) {
        // 新增用户与角色管理
        insertUserRole(user, true);
        SysUser sysUser = BeanUtil.toBean(user, SysUser.class);
        int flag = baseMapper.updateById(sysUser);
        if (flag < 1) {
            throw new ServiceException("修改用户" + user.getUserName() + "信息失败");
        }
        return flag;
    }

    @Override
    public int insertUser(SysUserBo user) {
        SysUser sysUser = BeanUtil.toBean(user, SysUser.class);
        int flag = baseMapper.insert(sysUser);
        user.setId(sysUser.getId());
        //新增用户与角色关系
        insertUserRole(user, false);
        return flag;
    }

    @Override
    public void exportExcel(SysUserBo user, HttpServletResponse response) {
        List<SysUserVo> list = baseMapper.selectUserList(user);
        List<SysUserExportVo> exportList = BeanUtil.copyToList(list, SysUserExportVo.class);
        ExcelUtil.exportExcel(exportList, "用户数据", SysUserExportVo.class, response);
    }

    @Override
    public List<SysUser> selectUserListByDept(Long deptId) {
        return baseMapper.selectList(new LambdaQueryWrapper<SysUser>().eq(SysUser::getDeptId,deptId).orderByAsc(SysUser::getId));
    }

    /**
     * 新增用户角色信息
     *
     * @param user  用户对象
     * @param clear 清除已存在的关联数据
     */
    private void insertUserRole(SysUserBo user, boolean clear) {
        this.insertUserRole(user.getId(), user.getRoleIds(), clear);
    }


    /**
     * 新增用户角色信息
     *
     * @param userId  用户ID
     * @param roleIds 角色组
     * @param clear   清除已存在的关联数据
     */
    private void insertUserRole(Long userId, Long[] roleIds, boolean clear) {
        if (ArrayUtil.isNotEmpty(roleIds)) {
            List<Long> roleList = new ArrayList<>(List.of(roleIds));
            // 判断是否具有此角色的操作权限
            if (clear) {
                // 删除用户与角色关联
                sysUserRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
            }
            // 新增用户与角色管理
            List<SysUserRole> list = StreamUtils.toList(roleList, roleId -> {
                SysUserRole ur = new SysUserRole();
                ur.setUserId(userId);
                ur.setRoleId(roleId);
                return ur;
            });
            sysUserRoleMapper.insert(list);
        }
    }
}
